{% extends "layout.html" %}
{% block body %}
<div x-data="{ ...rhasspy, 'slots': slots }">
    <div class="form-group">
        <div class="form-row text-muted pl-1">
            <p>
                Slots are named sets of values, referenced by <tt>$slotName</tt> in your sentences. A slot value can contain <tt>(alternative | words)</tt>, etc. like sentences.
            </p>
        </div>
    </div>
    <div class="form-group">
        <div class="form-row">
            <div class="col-xs-auto">
                <button onclick="saveSlots()" x-bind:class="{ 'btn-danger': slots.isDirty.value }" class="btn btn-primary">Save Slots</button>
            </div>
            <div class="col-xs-auto">
                <select id="slotKeys" class="form-control" x-model="slots.currentKey">
                    <option disabled>No slots</option>
                </select>
            </div>
            <div class="col-xs-auto">
                <button type="button" class="btn btn-success" onclick="$('#newSlotModal').modal('show')">New Slot</button>
            </div>
        </div>
    </div>
    <div class="form-group">
        <div class="form-row">
            <textarea x-model="slots.currentText.value" x-bind:class="{ 'border-danger': slots.isDirty.value }" class="form-control" style="border-width: 3px" type="text" rows="25" @input="slots.isDirty = true"></textarea>
        </div>
    </div>
    <div class="form-group">
        <div class="form-row">
            <button onclick="saveSlots()" x-bind:class="{ 'btn-danger': slots.isDirty.value }" class="btn btn-primary">Save Slots</button>
        </div>
    </div>
</div>

<div id="newSlotModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="newSlotModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 id="newSlotModalLabel" class="modal-title">New Slot</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <input id="newSlotKey" x-model="slots.newKey" type="text" class="form-control" placeholder="Slot Name">
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                <button type="button" class="btn btn-primary" onclick="makeNewSlot()">New Slot</button>
            </div>
        </div>
    </div>
</div>
{% endblock %}

{% block script %}
<script type="text/javascript">
 var slots = {
     isDirty: { value: false },
     currentText: {
         _value: '',
         get value() { return this._value; },
         set value(v) {
             this._value = v;
             slots.textByKey[slots.currentKey] = v;
         }
     },

     newKey: '',
     textByKey: {},

     _currentKey: '',
     get currentKey() {
         return this._currentKey;
     },

     set currentKey(value) {
         this._currentKey = value;
         this.currentText.value = this.textByKey[value];
     }
 }

 function syncKeys() {
     $('#slotKeys option').remove();
     Object.keys(slots.textByKey).forEach((k) => {
         $('#slotKeys').append(
             '<option>' + k + '</option>'
         )
     })
 }
 
 function saveSlots() {
     // Convert to lists
     var slotsLists = Object.fromEntries(
         Object.entries(slots.textByKey)
               .map((kv) => [kv[0], kv[1].split('\n')])
     );

     rhasspy.postBusy('Saving slots',
                      '/api/slots?overwriteAll=true',
                      JSON.stringify(slotsLists),
                      false)
            .done(function() {
                slots.isDirty = false;

                if (window.confirm("Slots saved. Retrain Rhasspy?")) {
                    rhasspy.train();
                } else {
                    rhasspy.hideBusy();
                }
            });
 }

 function makeNewSlot() {
     if (slots.newKey.length == 0) {
         alert('Please enter a slot name');
         return;
     }

     if (slots.newKey in slots.textByKey) {
         alert('Slot already exists');
     } else {
         $('#newSlotModal').modal('hide');
         slots.textByKey[slots.newKey] = '';
         syncKeys();
         slots.currentKey = slots.newKey;
         slots.newKey = '';
     }
 }

 // Warn user that slots haven't been saved
 window.onbeforeunload = () => {
     if (slots.isDirty.value) {
         return 'Slots were not saved. Are you sure?"'
     }
 }

 $(document).ready(() => {
     // Load slots on start up
     $.get({
         url: '{{ url_prefix }}/api/slots',
         dataType: 'json',
     }).done((r) => {
         slots.textByKey = Object.fromEntries(
             Object.entries(r)
             .map((kv) => [kv[0], kv[1].join('\n')])
         );

         syncKeys();

         if (!$.isEmptyObject(slots.textByKey)) {
             slots.currentKey = Object.keys(slots.textByKey)[0];
         }
     })

     // Catch ENTER in dialog
     $("#newSlotKey").keypress(() => {
         if (event.which == 13) {
             event.preventDefault();
             makeNewSlot();
         }
     })

     // Focus text box when dialog shown
     $('#newSlotModal').on('shown.bs.modal', () => {
         $('#newSlotKey').focus();
     })
 })
</script>
{% endblock %}
